/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.br.imovel.ejb;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import javax.persistence.EntityManager;
import javax.persistence.TypedQuery;
import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

/**
 *
 * @author adao
 */
public abstract class EJBFacade<T> {

    private Class<T> entidadeClass;
    private String ordenacao;
    private String ordem;
    
    protected abstract EntityManager getEntityManager();
    
    public EJBFacade(Class<T> entidadeClass, String ordenacao, String ordem) {
        this.entidadeClass = entidadeClass;
        this.ordenacao = ordenacao;
        this.ordem = ordem;
    }

    public void novo(T entidade) {
        getEntityManager().persist(entidade);
    }
    
    public T novoId(T entidade) {
        getEntityManager().persist(entidade);
        getEntityManager().flush();
        return entidade;
    }

    public void atualiza(T entidade) {
        getEntityManager().merge(entidade);
    }

    public void remove(T entidade) {
        getEntityManager().remove(getEntityManager().merge(entidade));
    }

    public T recupera(Object id) {
        return getEntityManager().find(entidadeClass, id);
    }

    public List<T> recuperaTodos() {

        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery cq = cb.createQuery(entidadeClass);
        Root<T> root = cq.from(entidadeClass);

        if (ordem.equals("desc")) {
            cq.orderBy(cb.desc(root.get(ordenacao)));
        } else if (ordem.equals("asc")) {
            cq.orderBy(cb.asc(root.get(ordenacao)));
        }

        return getEntityManager().createQuery(cq).getResultList();

    }

    public int quantidadeRegistros() {
        javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
        javax.persistence.criteria.Root<T> rt = cq.from(entidadeClass);
        cq.select(getEntityManager().getCriteriaBuilder().count(rt));
        javax.persistence.Query q = getEntityManager().createQuery(cq);
        return ((Long) q.getSingleResult()).intValue();
    }

    public List<T> localiza(Map<String, Object> argumentos) {

        CriteriaBuilder cb = getEntityManager().getCriteriaBuilder();
        CriteriaQuery<T> cq = cb.createQuery(entidadeClass);
        Root<T> root = cq.from(entidadeClass);

        List<Predicate> predicates = new ArrayList<Predicate>();
        //Acionando as Restriçoesna query
        for (Entry<String, Object> e : argumentos.entrySet()) {
            predicates.add(cb.equal(root.get(e.getKey()), e.getValue()));
        }
        cq.where(predicates.toArray(new Predicate[]{}));
        TypedQuery<T> q = getEntityManager().createQuery(cq);

        //O mÃ©todo getSingleResult() lanÃ§a uma exceÃ§Ã£o se o resultado for nulo

        return q.getResultList();

    }
    /*@Deprecated
     public List<T> localiza(int[] range) {
     javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
     cq.select(cq.from(entidadeClass));
     javax.persistence.Query q = getEntityManager().createQuery(cq);
     q.setMaxResults(range[1] - range[0]);
     q.setFirstResult(range[0]);
     return q.getResultList();
     }*/
}
